using System;
using System.Collections.Generic;
using System.ComponentModel.Composition;
using System.ComponentModel.Composition.Hosting;
using System.ComponentModel.Composition.ReflectionModel;
using System.Linq;
using Caliburn.Micro;
using Action = System.Action;

namespace MediaOwl.Core.Modularity
{
    public class RemoveCatalog : IResult
    {
        static readonly Dictionary<string, DeploymentCatalog> catalogs = new Dictionary<string, DeploymentCatalog>();
        private readonly IModuleManager moduleManager;
        private readonly Uri uri;
        private readonly Action onSuccess;
        private readonly Action<Exception> onFail;

        [Import]
        public AggregateCatalog Catalog { get; set; }

        public RemoveCatalog(Uri uri, IModuleManager moduleManager, Action onSuccess, Action<Exception> onFail)
        {
            this.moduleManager = moduleManager;
            this.uri = uri;
            this.onSuccess = onSuccess;
            this.onFail = onFail;
        }

        public void Execute(ActionExecutionContext context)
        {
            var catalog = moduleManager.GetCatalog(uri.ToString());
            //var catalog = Catalog.Catalogs.OfType<DeploymentCatalog>().FirstOrDefault(x => x.Uri == uri);

            if (catalog != null)
            {
                ((ModuleManager)moduleManager).RemoveCatalog(uri.ToString());

                catalog.Parts
                    .Select(part => ReflectionModelServices.GetPartType(part).Value.Assembly)
                    .Where(assembly => AssemblySource.Instance.Contains(assembly))
                    .Apply(x => AssemblySource.Instance.Remove(x));

                Catalog.Catalogs.Remove(catalog);
                catalogs.Remove(uri.ToString());

                var module = moduleManager.Modules.FirstOrDefault(x => x.Uri == uri);
                if (module != null)
                    module.Loaded = false;

                if (onSuccess != null)
                    Caliburn.Micro.Execute.OnUIThread(() => onSuccess());
                Completed(this, new ResultCompletionEventArgs());
            }
            else
            {
                var err = new Exception("Could not get the catalog to remove the xap.");

                if (onFail != null)
                    Caliburn.Micro.Execute.OnUIThread(() => onFail(err));

                Completed(this, new ResultCompletionEventArgs
                                    {
                                        Error = err,
                                        WasCancelled = false
                                    });
            }
        }

        public event EventHandler<ResultCompletionEventArgs> Completed = delegate { };
    }
}